/**
 *
 */
package jp.seraph.jspf.codec;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Iterator;
import java.util.Map;

import net.sf.json.JSONObject;

import jp.seraph.jsade.math.Angle;
import jp.seraph.jsade.model.JointIdentifier;
import jp.seraph.jsade.model.JointIdentifierContainer;
import jp.seraph.jspf.pose.DefaultPose;
import jp.seraph.jspf.pose.Pose;

/**
 * PoseをJson形式にエンコード・デコードするコーデックです。
 */
public class JsonPoseCodec implements PoseCodec {
    public JsonPoseCodec(JointIdentifierContainer aJointMapper) {
        mJointMapper = aJointMapper;
    }

    private JointIdentifierContainer mJointMapper;

    /**
     * 
     * @see jp.seraph.jspf.codec.PoseDecoder#decode(java.io.Reader)
     */
    public Pose decode(Reader aReader) throws IOException {
        DefaultPose tResult = new DefaultPose();

        JSONObject tObject = JSONObject.fromObject(this.readToEnd(aReader));
        Iterator<String> tKeyIterator = getIterator(tObject);
        while (tKeyIterator.hasNext()) {
            String tKey = (String) tKeyIterator.next();
            tResult.setJointAngle(mJointMapper.getIdentifier(tKey), Angle.createAngleAsDegree(tObject.getDouble(tKey)));
        }

        return tResult;
    }

    private String readToEnd(Reader aReader) throws IOException {
        BufferedReader tReader = new BufferedReader(aReader);
        StringBuilder tBuilder = new StringBuilder();
        String tLine;
        while ((tLine = tReader.readLine()) != null) {
            tBuilder.append(tLine);
            tBuilder.append(System.getProperty("line.separator"));
        }

        return tBuilder.toString();
    }

    /**
     * 
     * @see jp.seraph.jspf.codec.PoseEncoder#encode(jp.seraph.jspf.pose.Pose,
     *      java.io.Writer)
     */
    public void encode(Pose aPose, Writer aWriter) throws IOException {
        JSONObject tJson = new JSONObject();

        for (Map.Entry<JointIdentifier, Angle> tEntry : aPose) {
            tJson.put(tEntry.getKey(), tEntry.getValue().getDegree());
        }

        aWriter.write(tJson.toString());
    }

    @SuppressWarnings("unchecked")
    private Iterator<String> getIterator(JSONObject aIterable) {
        return (Iterator<String>) aIterable.keys();
    }
}
